package com.meiya.hugegraph.example;

import org.apache.hugegraph.driver.GremlinManager;
import org.apache.hugegraph.driver.HugeClient;
import org.apache.hugegraph.structure.gremlin.Result;
import org.apache.hugegraph.structure.gremlin.ResultSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.meiya.hugegraph.api.HugeGraphClientFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 使用Gremlin进行复杂交易图查询示例
 * 展示如何使用Gremlin查询语言进行更复杂的图遍历和分析
 */
public class TransactionGremlinExample {
    
    private static final Logger logger = LoggerFactory.getLogger(TransactionGremlinExample.class);
    
    public static void main(String[] args) {
        HugeClient client = null;
        
        try {
            // 创建HugeClient
            client = HugeGraphClientFactory.createClient();
            
            // 获取Gremlin管理器
            GremlinManager gremlin = client.gremlin();
            
            // 执行各种Gremlin查询
            
            // 1. 查询所有银行卡
            logger.info("===== 查询所有银行卡 =====");
            executeAndPrintQuery(gremlin, "g.V().hasLabel('card')");
            
            // 2. 查询张三的银行卡
            logger.info("===== 查询张三的银行卡 =====");
            executeAndPrintQuery(gremlin, "g.V().hasLabel('card').has('holderName', '张三')");
            
            // 3. 查询交易金额大于500的交易边
            logger.info("===== 查询交易金额大于500的交易 =====");
            executeAndPrintQuery(gremlin, "g.E().hasLabel('transaction').has('amount', gt(500))");
            
            // 4. 查询张三参与的所有交易
            logger.info("===== 查询张三参与的所有交易 =====");
            executeAndPrintQuery(gremlin, 
                    "g.V().has('card', 'holderName', '张三')" +
                    ".both('transaction')" +
                    ".path().by('holderName').by('amount')");
            
            // 5. 查询交易金额从大到小排序
            logger.info("===== 查询交易金额从大到小排序 =====");
            executeAndPrintQuery(gremlin, 
                    "g.E().hasLabel('transaction')" +
                    ".order().by('amount', decr)" +
                    ".limit(10)" +
                    ".valueMap()");
            
            // 6. 查询交易路径（2跳以内）
            logger.info("===== 查询交易路径（2跳以内）=====");
            executeAndPrintQuery(gremlin, 
                    "g.V().has('card', 'holderName', '张三')" +
                    ".repeat(both('transaction').simplePath()).times(2)" +
                    ".path().by('holderName').by('amount')");
            
            // 7. 统计每个人的交易总额
            logger.info("===== 统计每个人的交易总额 =====");
            executeAndPrintQuery(gremlin, 
                    "g.V().hasLabel('card')" +
                    ".project('name', 'outTotal', 'inTotal')" +
                    ".by('holderName')" +
                    ".by(outE('transaction').values('amount').sum())" +
                    ".by(inE('transaction').values('amount').sum())");
            
            // 8. 查找交易环路
            logger.info("===== 查找交易环路 =====");
            executeAndPrintQuery(gremlin, 
                    "g.V().hasLabel('card')" +
                    ".repeat(both('transaction').simplePath())" +
                    ".until(loops().is(gte(1)).and().out('transaction')" +
                    ".where(eq('__')))" +
                    ".path().by('holderName').by('amount')" +
                    ".limit(5)");
            
            // 9. 使用参数化查询
            logger.info("===== 使用参数化查询 =====");
            String parametrizedQuery = "g.V().has('card', 'holderName', name).outE('transaction')";
            Map<String, Object> params = new HashMap<>();
            params.put("name", "张三");
            executeParameterizedQuery(gremlin, parametrizedQuery, params);
            
        } catch (Exception e) {
            logger.error("Gremlin查询示例执行出错", e);
        } finally {
            // 关闭client
            HugeGraphClientFactory.closeClient(client);
        }
    }
    
    /**
     * 执行查询并打印结果
     * 
     * @param gremlin Gremlin管理器
     * @param query Gremlin查询语句
     */
    private static void executeAndPrintQuery(GremlinManager gremlin, String query) {
        try {
            logger.info("执行查询: {}", query);

            execute(gremlin, query);
            
        } catch (Exception e) {
            logger.error("查询执行失败: {}", query, e);
        }
    }

    private static void execute(GremlinManager gremlin, String query) {
        ResultSet resultSet = gremlin.gremlin(query).execute();

        List<Result> results = new ArrayList<>();
        resultSet.iterator().forEachRemaining(results::add);

        logger.info("查询结果数量: {}", results.size());
        for (int i = 0; i < results.size(); i++) {
            logger.info("结果 {}: {}", i + 1, results.get(i).getObject());
        }

        logger.info("----------------------------");
    }

    /**
     * 执行带参数的查询并打印结果
     * 
     * @param gremlin Gremlin管理器
     * @param query Gremlin查询语句
     * @param params 查询参数
     */
    private static void executeParameterizedQuery(GremlinManager gremlin, String query, Map<String, Object> params) {
        try {
            logger.info("执行参数化查询: {}, 参数: {}", query, params);
            
            // 替换查询中的参数
            String processedQuery = query;
            for (Map.Entry<String, Object> param : params.entrySet()) {
                String paramName = param.getKey();
                Object paramValue = param.getValue();
                
                // 简单字符串替换，实际应用中可能需要更复杂的处理
                if (paramValue instanceof String) {
                    processedQuery = processedQuery.replace(paramName, "'" + paramValue + "'");
                } else {
                    processedQuery = processedQuery.replace(paramName, paramValue.toString());
                }
            }
            
            logger.info("处理后的查询: {}", processedQuery);

            execute(gremlin, query);

        } catch (Exception e) {
            logger.error("参数化查询执行失败: {}", query, e);
        }
    }
} 